package mapcreatorpackage;

import java.util.Random;

public class MapBuilder {

	int width, high;

	/**
	 * constructor
	 */
	public MapBuilder(int width, int high) {
		if (width < 3 || high < 3) {
			System.out.println("Width and high has to be set 3 as minimum.");
		}
		this.width = width;
		this.high = high;
	}

	/**
	 * fills a level with free fields: '_'
	 * 
	 * @return a filled level
	 */
	public char[][] fillALevelMap() {
		char[][] newMap = new char[high][width];
		// fill with empty: '_'
		for (int j = 0; j < high; j++) {
			for (int i = 0; i < width; i++) {
				newMap[j][i] = '_';
			}
		}
		return newMap;
	}

	/**
	 * 
	 * @param lvl
	 * @return lvl
	 */
	public char[][] createTheLevel(int h, int w) {
		
		char[][] lvl = new char[h][w];
		// fill with empty: '_'
		for (int j = 0; j < h; j++) {
			for (int i = 0; i < w; i++) {
				lvl[j][i] = '_';
			}
		}

		Random rdm = new Random();
		int forWayLength = Math.min(high, width);
		int direction = rdm.nextInt(3);
		int wayLength = rdm.nextInt(forWayLength) + 2;
		// int setDirection = 4;
		int oldDirection = 4;
		//
//		boolean switchedDirection = false;
		boolean somethingWasSet = false;
		boolean aRB0a3skipped = false;
		boolean triedTop = false;
		boolean triedBottom = false;
		boolean triedLeft = false;
		boolean triedRight = false;
		//
		int maxPartsToSet = Math.round(width * high / 3);
		int coord1 = rdm.nextInt(width);
		int coord2 = rdm.nextInt(high);

		int xold = coord1, yold = coord2;
		// set start point S
		lvl[coord2][coord1] = 'S';

		// set way points
		while (maxPartsToSet > 0) {
			// skip from 3 back to 0
			if (direction > 3 && !aRB0a3skipped) {
				direction = 0;
				aRB0a3skipped = true;
			}
			// needed to avoid endless loop
			if (aRB0a3skipped && direction > 3) {

				break;
			}

			if (triedTop && triedBottom && triedLeft && triedRight) {

				break;
			}
			// fill the map

			// try top
			if (direction == 0 && !triedTop) {
				while (wayLength > 1 && maxPartsToSet > 0) {
					// does field exist?
					if (coord2 - 1 >= 0) {
						// already set something here?
						if (lvl[coord2 - 1][coord1] == '_') {
							// check whether old points to next
							if (lvl[yold][xold] != 'S') {
								if (oldDirection == 0) {
									if (lvl[yold][xold] != '^') {
										lvl[yold][xold] = '^';
									}
								}
								if (oldDirection == 1) {
									if (lvl[yold][xold] != '<') {
										lvl[yold][xold] = '<';
									}
								}
								if (oldDirection == 2) {
									if (lvl[yold][xold] != 'v') {
										lvl[yold][xold] = 'v';
									}
								}
								if (oldDirection == 3) {
									if (lvl[yold][xold] != '>') {
										lvl[yold][xold] = '>';
									}
								}
							}
							// set point
							lvl[coord2 - 1][coord1] = '^';
							xold = coord1;
							yold = coord2;
							coord2--;
							wayLength--;
							maxPartsToSet--;
							oldDirection = direction;
							somethingWasSet = true;
						} else {
							// field was not free
							triedTop = true;
							direction++;
							break;
						}
					} else {
						// field was not valid
						triedTop = true;
						direction++;
						break;
					}
				}
				if (somethingWasSet) {
					// coming direction
					direction = rdm.nextInt(3);
					wayLength = rdm.nextInt(forWayLength) + 2;
					triedTop = false;
					triedBottom = false;
					triedLeft = false;
					triedRight = false;
					aRB0a3skipped = false;
					somethingWasSet = false;
					continue;
				}
			}
			// }

			// try left
			// if (setDirection == 1 || setDirection == 0) {
			if (direction == 1 && !triedLeft) {
				while (wayLength > 1 && maxPartsToSet > 0) {
					// does field exist?
					if (coord1 - 1 >= 0) {
						// already set something here?
						if (lvl[coord2][coord1 - 1] == '_') {
							// check whether old points to next
							if (lvl[yold][xold] != 'S') {
								if (oldDirection == 0) {
									if (lvl[yold][xold] != '^') {
										lvl[yold][xold] = '^';
									}
								}
								if (oldDirection == 1) {
									if (lvl[yold][xold] != '<') {
										lvl[yold][xold] = '<';
									}
								}
								if (oldDirection == 2) {
									if (lvl[yold][xold] != 'v') {
										lvl[yold][xold] = 'v';
									}
								}
								if (oldDirection == 3) {
									if (lvl[yold][xold] != '>') {
										lvl[yold][xold] = '>';
									}
								}
							}
							// set point
							lvl[coord2][coord1 - 1] = '<';
							xold = coord1;
							yold = coord2;
							coord1--;
							wayLength--;
							maxPartsToSet--;
							oldDirection = direction;
							somethingWasSet = true;
						} else {
							// field was not free
							triedLeft = true;
							direction++;
							break;
						}
					} else {
						// field was not valid
						triedLeft = true;
						direction++;
						break;
					}
				}
				if (somethingWasSet) {
					direction = rdm.nextInt(3);
					wayLength = rdm.nextInt(forWayLength) + 2;
					triedTop = false;
					triedBottom = false;
					triedLeft = false;
					triedRight = false;
					aRB0a3skipped = false;
					somethingWasSet = false;
					continue;
				}
			}
			// }

			// try bottom
			if (direction == 2 && !triedBottom) {
				while (wayLength > 1 && maxPartsToSet > 0) {
					// does field exist?
					if (coord2 + 1 < high) {
						// already set something here?
						if (lvl[coord2 + 1][coord1] == '_') {
							// check whether old points to next
							if (lvl[yold][xold] != 'S') {
								if (oldDirection == 0) {
									if (lvl[yold][xold] != '^') {
										lvl[yold][xold] = '^';
									}
								}
								if (oldDirection == 1) {
									if (lvl[yold][xold] != '<') {
										lvl[yold][xold] = '<';
									}
								}
								if (oldDirection == 2) {
									if (lvl[yold][xold] != 'v') {
										lvl[yold][xold] = 'v';
									}
								}
								if (oldDirection == 3) {
									if (lvl[yold][xold] != '>') {
										lvl[yold][xold] = '>';
									}
								}
							}
							// set point
							lvl[coord2 + 1][coord1] = 'v';
							xold = coord1;
							yold = coord2;
							coord2++;
							wayLength--;
							maxPartsToSet--;
							oldDirection = direction;
							somethingWasSet = true;
						} else {
							// field was not free
							triedBottom = true;
							direction++;
							break;
						}
					} else {
						// field was not valid
						triedBottom = true;
						direction++;
						break;
					}
				}
				if (somethingWasSet) {
					direction = rdm.nextInt(3);
					wayLength = rdm.nextInt(forWayLength) + 2;
					triedTop = false;
					triedBottom = false;
					triedLeft = false;
					triedRight = false;
					aRB0a3skipped = false;
					continue;
				}
			}
			// }

			// try right
			if (direction == 3 && !triedRight) {
				while (wayLength > 1 && maxPartsToSet > 0) {
					// does field exist?
					if (coord1 + 1 < width) {
						// already set something here?
						if (lvl[coord2][coord1 + 1] == '_') {
							// check whether old points to next
							if (lvl[yold][xold] != 'S') {
								if (oldDirection == 0) {
									if (lvl[yold][xold] != '^') {
										lvl[yold][xold] = '^';
									}
								}
								if (oldDirection == 1) {
									if (lvl[yold][xold] != '<') {
										lvl[yold][xold] = '<';
									}
								}
								if (oldDirection == 2) {
									if (lvl[yold][xold] != 'v') {
										lvl[yold][xold] = 'v';
									}
								}
								if (oldDirection == 3) {
									if (lvl[yold][xold] != '>') {
										lvl[yold][xold] = '>';
									}
								}
							}
							// set point
							lvl[coord2][coord1 + 1] = '>';
							xold = coord1;
							yold = coord2;
							coord1++;
							wayLength--;
							maxPartsToSet--;
							oldDirection = direction;
							somethingWasSet = true;
						} else {
							// field was not free
							triedRight = true;
							direction++;
							break;
						}
					} else {
						// field was not valid
						triedRight = true;
						direction++;
						break;
					}
				}
				if (somethingWasSet) {
					direction = rdm.nextInt(3);
					wayLength = rdm.nextInt(forWayLength) + 2;
					triedTop = false;
					triedBottom = false;
					triedLeft = false;
					triedRight = false;
					aRB0a3skipped = false;
					continue;
				}
			}
			// }

			direction++;
		}
		// set X here
		if (lvl[yold][xold] != 'S') {
			if (oldDirection == 0) {
				if (lvl[yold][xold] != '^') {
					lvl[yold][xold] = '^';
				}
			}
			if (oldDirection == 1) {
				if (lvl[yold][xold] != '<') {
					lvl[yold][xold] = '<';
				}
			}
			if (oldDirection == 2) {
				if (lvl[yold][xold] != 'v') {
					lvl[yold][xold] = 'v';
				}
			}
			if (oldDirection == 3) {
				if (lvl[yold][xold] != '>') {
					lvl[yold][xold] = '>';
				}
			}
		}
		lvl[coord2][coord1] = 'X';

		return lvl;
	}

	private void printTheMap(char[][] level) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < level.length; i++) {
			for (int j = 0; j < level[0].length; j++) {
				sb.append(level[i][j]);
			}
			sb.append("\n");
		}
		System.out.println(sb);
	}

	public static void main(String[] args) {
		MapBuilder myOne = new MapBuilder(8, 8);
		myOne.printTheMap(myOne.createTheLevel(8,8));
		// myOne.printTheMap(myOne.fillALevelMap());
	}

}
